﻿using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Admin.NET.Core;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq.Dynamic.Core;
using Microsoft.AspNetCore.Http;
using System.Text;
using System.Web;
using System.ComponentModel;
using System.Data;
namespace Admin.NET.Application
{
    /// <summary>
    /// 测试学生表服务
    /// </summary>
    [ApiDescriptionSettings("TestDemo", Name = "TestStudent5", Order = 100)]
    [Route("api/[Controller]")]
    public class TestStudent5Service : ITestStudent5Service, IDynamicApiController, ITransient
    {
        private readonly IRepository<TestStudent5,MasterDbContextLocator> _testStudent5Rep;
        private readonly IRepository<SysDictType, MasterDbContextLocator> _sysDictTypeRep;
        private readonly IRepository<SysDictData, MasterDbContextLocator> _sysDictDataRep;
        private readonly ISysExcelTemplateService _sysExcelTemplateService;
        private readonly static object _lock = new();

        public TestStudent5Service(
            IRepository<TestStudent5,MasterDbContextLocator> testStudent5Rep
            ,IRepository<SysDictType, MasterDbContextLocator> sysDictTypeRep
            ,IRepository<SysDictData, MasterDbContextLocator> sysDictDataRep
            ,ISysExcelTemplateService sysExcelTemplateService
        )
        {
            _testStudent5Rep = testStudent5Rep;
         _sysDictTypeRep = sysDictTypeRep;
         _sysDictDataRep = sysDictDataRep;
         _sysExcelTemplateService = sysExcelTemplateService;
        }

        /// <summary>
        /// 分页查询测试学生表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [Description("TestStudent5/page")]
        [HttpGet("page")]
        public async Task<PageResult<TestStudent5Output>> Page([FromQuery] TestStudent5Search input)
        {
            var testStudent5s = await _testStudent5Rep.DetachedEntities
                                     .Where(!string.IsNullOrEmpty(input.Name), u => u.Name == input.Name)
                                     .Where(input.Age != null, u => u.Age == input.Age)
                                     .Where(input.CreatedTime!=null, u => u.CreatedTime>=  Convert.ToDateTime(input.CreatedTime[0]) && u.CreatedTime<= Convert.ToDateTime(input.CreatedTime[1]))
                                     .Where(input.UpdatedTime!=null, u => u.UpdatedTime>=  Convert.ToDateTime(input.UpdatedTime[0]) && u.UpdatedTime<= Convert.ToDateTime(input.UpdatedTime[1]))
                                     .Where(!string.IsNullOrEmpty(input.CreatedUserName), u => u.CreatedUserName == input.CreatedUserName)
                                     .Where(!string.IsNullOrEmpty(input.UpdatedUserName), u => u.UpdatedUserName == input.UpdatedUserName)
                                     .OrderBy(PageInputOrder.OrderBuilder<TestStudent5Search>(input))
                                     .ProjectToType<TestStudent5Output>()
                                     .ToADPagedListAsync(input.PageNo, input.PageSize);
            return testStudent5s;
        }

        /// <summary>
        /// 不分页查询测试学生表列表
        /// </summary>
        /// <param name="input">测试学生表查询参数</param>
        /// <returns>(测试学生表)实例列表</returns>
        [Description("TestStudent5/listNonPage")]
        [HttpGet("listNonPage")]
        public async Task<List<TestStudent5Output>> ListNonPageAsync([FromQuery] TestStudent5SearchNonPage input)
        {
            var pName = input.Name?.Trim() ?? "";
            var pAge = input.Age;
            var pCreatedTime = input.CreatedTime;
            var pUpdatedTime = input.UpdatedTime;
            var pCreatedUserName = input.CreatedUserName?.Trim() ?? "";
            var pUpdatedUserName = input.UpdatedUserName?.Trim() ?? "";
            var testStudent5s = await _testStudent5Rep.DetachedEntities
                .Where(!string.IsNullOrEmpty(pName), u => u.Name == pName)
                .Where(pAge != null, u => u.Age == pAge)
           .Where(input.CreatedTime!=null, u => u.CreatedTime>=  Convert.ToDateTime(input.CreatedTime[0]) && u.CreatedTime<= Convert.ToDateTime(input.CreatedTime[1]))
           .Where(input.UpdatedTime!=null, u => u.UpdatedTime>=  Convert.ToDateTime(input.UpdatedTime[0]) && u.UpdatedTime<= Convert.ToDateTime(input.UpdatedTime[1]))
                .Where(!string.IsNullOrEmpty(pCreatedUserName), u => u.CreatedUserName == pCreatedUserName)
                .Where(!string.IsNullOrEmpty(pUpdatedUserName), u => u.UpdatedUserName == pUpdatedUserName)
            .OrderBy(PageInputOrder.OrderNonPageBuilder(input))
            .ProjectToType<TestStudent5Output>()
            .ToListAsync();
            return testStudent5s;
        }


        /// <summary>
        /// 增加测试学生表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [Description("TestStudent5/add")]
        [HttpPost("add")]
        public async Task Add(AddTestStudent5Input input)
        {
            var testStudent5 = input.Adapt<TestStudent5>();
                        //验证
            await CheckExisit(testStudent5);
            await _testStudent5Rep.InsertAsync(testStudent5);
        }

        /// <summary>
        /// 删除测试学生表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [Description("TestStudent5/delete")]
        [HttpPost("delete")]
        public async Task Delete(DeleteTestStudent5Input input)
        {
            var testStudent5 = await _testStudent5Rep.FirstOrDefaultAsync(u => u.Id == input.Id);
            await _testStudent5Rep.DeleteAsync(testStudent5);
        }

        /// <summary>
        /// 更新测试学生表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [Description("TestStudent5/edit")]
        [HttpPost("edit")]
        public async Task Update(UpdateTestStudent5Input input)
        {
            var isExist = await _testStudent5Rep.AnyAsync(u => u.Id == input.Id, false);
            if (!isExist) throw Oops.Oh(ErrorCode.D1002);

            var testStudent5 = input.Adapt<TestStudent5>();
            //验证
            await CheckExisit(testStudent5,true);
            await _testStudent5Rep.UpdateAsync(testStudent5,ignoreNullValues:true);
        }

        /// <summary>
        /// 获取测试学生表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [Description("TestStudent5/detail")]
        [HttpGet("detail")]
        public async Task<TestStudent5Output> Get([FromQuery] QueryeTestStudent5Input input)
        {
            return (await _testStudent5Rep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id)).Adapt<TestStudent5Output>();
        }

        /// <summary>
        /// 获取测试学生表列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [Description("TestStudent5/list")]
        [HttpGet("list")]
        public async Task<List<TestStudent5Output>> List([FromQuery] TestStudent5Input input)
        {
            return await _testStudent5Rep.DetachedEntities.ProjectToType<TestStudent5Output>().ToListAsync();
        }    
         /// <summary>
        /// Excel模板导入测试学生表功能
        /// </summary>
        /// <param name="file">Excel模板文件</param>
        /// <param name="importExcelType">Excel导入方式</param>
        /// <returns>导入的记录数</returns>
        [HttpPost("fromExcel")]
        public async Task<int> FromExcelAsync(IFormFile file, [FromQuery] ImportExcelType importExcelType)
        { 
            int _HeadStartLine = 2;//第1行是说明,第2行是列名
            int _DataStartLine = 3;//第3行开始是数据

            DataTable importDataTable = ExcelUtil.ImportExcelToDataTable(file, _HeadStartLine, _DataStartLine);
            var addList =await CommonImport(importDataTable, _DataStartLine);

            lock (_lock)
            {
                _testStudent5Rep.InsertAsync(addList);
               
            }
            await Task.CompletedTask;
            return addList.Count;
        }

        /// <summary>
        ///  DataTable转换实体对象列表
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="dataStartLine">模版列名开始行</param>
        /// <returns></returns>
          private async Task<List<TestStudent5>> CommonImport(DataTable dataTable, int dataStartLine)
        {

            var details = new List<TestStudent5>();
            int index = dataStartLine;//模版列名开始行
            foreach (System.Data.DataRow row in dataTable.Rows)
            {
                index++;

               //导入模版定制化代码（替换模版使用）
                                          
                           var addItem = new TestStudent5()
                            {
                               CreatedTime = DateTime.Now,
                               CreatedUserId = CurrentUserInfo.UserId,
                               CreatedUserName = CurrentUserInfo.Name,
                               UpdatedTime = DateTime.Now,
                               UpdatedUserId = CurrentUserInfo.UserId,
                               UpdatedUserName = CurrentUserInfo.Name
                             };
                          #region 定义变量
                           var _Name = "";//姓名
                           var _Age = "";//年龄
                          #endregion
                          
                          
                          #region 取值
                           _Name = row["姓名"]?.ToString() ;
                           _Age = row["年龄"]?.ToString() ;
                          #endregion
                          
                          
                          #region 验证
                          if(!string.IsNullOrEmpty(_Name))
                          {
                                addItem.Name = (string)_Name;
                           }
                          if(!string.IsNullOrEmpty(_Age))
                          {
                              if (!int.TryParse(_Age, out int outAge)&&!string.IsNullOrEmpty(_Age))
                              {
                                 throw Oops.Oh($"第{index}行[年龄]{_Age}值不正确！");
                              }
                              if (outAge <= 0&&!string.IsNullOrEmpty(_Age))
                              {
                                 throw Oops.Oh($"第{index}行[年龄]{_Age}值不能小于等于0！");
                              }
                              else
                              {
                                 addItem.Age = outAge;
                              }
                          
                          }
                          #endregion
                          

                //验重
                await CheckExisit(details, addItem,index);
                details.Add(addItem);
            }

            return details;
        }

        /// <summary>
        /// 根据版本下载测试学生表的Excel导入模板
        /// </summary>
        /// <param name="version">模板版本</param>
        /// <returns>下载的模板文件</returns>
        [Description("TestStudent5/downloadExcelTemplate")]
        [HttpGet("downloadExcelTemplate")]
        public IActionResult DownloadExcelTemplate([FromQuery] string version)
        {
            string _path = TemplateConst.EXCEL_TEMPLATEFILE_导入模版路径 + $"\\TestStudent5{TemplateConst.EXCEL_TEMPLATEFILE_导入模版名称后缀}.xlsx";
            var fileName = HttpUtility.UrlEncode($"导入模板(测试学生表).xlsx", Encoding.GetEncoding("UTF-8"));
            return new FileStreamResult(new FileStream(_path, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };
        }

        /// <summary>
        /// 根据测试学生表查询参数导出Excel
        /// </summary>
        /// <param name="input">测试学生表查询参数</param>
        /// <returns>导出的Excel文件</returns>
        [Description("TestStudent5/toExcel")]
        [HttpGet("toExcel")]
        public async Task<IActionResult> ToExcelAsync([FromQuery] TestStudent5SearchNonPage input)
        {
            var testStudent5List = await ListNonPageAsync(input);
            MemoryStream ms = new();
            DataConvertUtil.ToExcelData(testStudent5List, _sysDictTypeRep, _sysDictDataRep, out List<string> headers, 
                out List<List<object>> data, out string sheetName);
            var excelTemplate = await _sysExcelTemplateService.GetByAppNameAndClassNameAndVersionAsync("TestStudent5", "v1");
            if (excelTemplate != null)
            {
                ExcelUtil.ToExcel(excelTemplate.TemplateFileName, headers, data, sheetName, excelTemplate.HeadStartLine, excelTemplate.DataStartLine, ms);
            }
            else 
            {
                ExcelUtil.ToExcel(headers, data, sheetName, ms);
            }
            ms.Position = 0;
            var fileName = HttpUtility.UrlEncode($"{sheetName}[{DateTimeOffset.Now:yyyy-MM-dd}].xlsx", Encoding.GetEncoding("UTF-8"));
            return new FileStreamResult(ms, "application/octet-stream") { FileDownloadName = fileName };
        }



        
        



        /// <summary>
        /// 根据联合主键验证数据是否已存在-数据库
        /// </summary>
        /// <param name="input"></param>
        /// <param name="isEdit"></param>
        /// <param name="index">导入模板excel行号</param>
        /// <returns></returns>
        private async Task CheckExisit( TestStudent5 input,bool isEdit=false,int index=0)
        {
           

           
           bool isExist = false;
           if (!isEdit)//新增
           {
                   //数据是否重复
                   isExist = await _testStudent5Rep.AnyAsync(u =>
                                   u.Name.Equals(input.Name)
                                   &&u.Age.Equals(input.Age)
                                   &&u.CreatedTime.Equals(input.CreatedTime)
                                   &&u.UpdatedTime.Equals(input.UpdatedTime)
                                   &&u.CreatedUserName.Equals(input.CreatedUserName)
                                   &&u.UpdatedUserName.Equals(input.UpdatedUserName)
                   ,false);
          }
           else//编辑 
          {

          
                
                 //数据是否重复
                  isExist = await _testStudent5Rep.AnyAsync(u => 
                                    u.Id == input.Id
                                    &&u.Age.Equals(input.Age)
                                    &&u.CreatedTime.Equals(input.CreatedTime)
                                    &&u.UpdatedTime.Equals(input.UpdatedTime)
                                    &&u.CreatedUserName.Equals(input.CreatedUserName)
                                    &&u.UpdatedUserName.Equals(input.UpdatedUserName)
                    ,false);
               }
               
        

           if (index > 0)
           {
               if (isExist) throw Oops.Oh($"第{index}行数据已存在");
           }
           else
           {
               if (isExist) throw Oops.Oh(ErrorCode.E0001);
           }

             
           
              

        }

        /// <summary>
        /// 根据联合主键验证数据是否已存在-导入的数据集
        /// </summary>
        /// <param name="inputs"></param>
        /// <param name="input"></param>
        /// <param name="index">导入模板excel行号</param>
        private async Task CheckExisit(List<TestStudent5> inputs,TestStudent5 input, int index)
        {

                 //导入的集合是否已存在相同数据  
                 var isExist = inputs.Any(u =>
                                 u.Name.Equals(input.Name)
                                 &&u.Age.Equals(input.Age)
                                 &&u.CreatedTime.Equals(input.CreatedTime)
                                 &&u.UpdatedTime.Equals(input.UpdatedTime)
                                 &&u.CreatedUserName.Equals(input.CreatedUserName)
                                 &&u.UpdatedUserName.Equals(input.UpdatedUserName)
                 );
                 if(isExist) throw Oops.Oh($"第{index}行数据已存在");
                 //数据库是否已存在相同数
                 await CheckExisit(input,false,index);
            
           
        }


    }
}
